package p2pcdnsim.cdn;

import java.util.HashMap;
import java.util.Iterator;

import desmoj.core.simulator.SimTime;

public class LRUCaching<T extends ObjectContent> implements CachingStrategy<T> {
	
	private  HashMap<Long,Entry> objects;
	private  long cacheSize;
	private  long currBytes;
	
	
	public LRUCaching() {
		objects = new HashMap<Long,Entry>();
		this.currBytes = 0;
	}
	
	public void setCacheSize(long size) {
		this.cacheSize = size;
	}

	@Override
	public T retrieveObject(long objectId, SimTime timeStamp) {
		Entry entry;
		if((entry = objects.get(objectId)) == null) return null;
		entry.timeStamp = timeStamp.getTimeValue(); //Updates the timestamp
		return entry.content;
	}

	@Override
	public boolean insertObject(T content, SimTime timeStamp) {
		//If there is not sufficient space to this object, do not try to cache
		if(content.getLength() > cacheSize) return false;
		
		//while there is not enough space, remove Last Recently Used
		while(currBytes + content.getLength() > cacheSize) removeLRU();

		Entry entry = new Entry();
		entry.content = content;
		entry.timeStamp = timeStamp.getTimeValue();
		currBytes += content.getLength();
		objects.put(content.getObjectId(), entry);
		return true;
	}
	
	
	// Ineficiente
	private void removeLRU() {
		Iterator<Entry> it = objects.values().iterator();
		Entry e = it.next();
		T content = e.content;
		double last = e.timeStamp;
		while(it.hasNext()) {
			e = it.next();
			if(e.timeStamp < last) {
				last = e.timeStamp;
				content = e.content;
			}
		}
		
		objects.remove(content.getObjectId());
		currBytes-=content.getLength();
	}
	
	private class Entry {
		public double timeStamp;
		public T content;	
	}

}
